using Firestarter.Test.Base;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.BO;
using NUnit.Framework;

namespace FireStarterModeller.Test.BO
{
    [TestFixture]
    public class TestDMSingleTableInheritanceSubClassShouldNotHaveObjectIdentity
    {
        [SetUp]
        public void SetupTest()
        {
            //Runs every time that any testmethod is executed
            TestUtilsDomain.SetupTest();
            BORegistry.DataAccessor = new DataAccessorInMemory();
        }

        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            //Code that is executed before any test is run in this class. If multiple tests
            // are executed then it will still only be called once.
            TestUtilsDomain.SetupFixture();
        }

        [TearDown]
        public void TearDownTest()
        {
            //runs every time any testmethod is complete
        }

        [Test]
        public void Test_Construct_ShouldSetupRuleNameAndErrorLevelToError()
        {
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            var rule = new DMSingleTableInheritanceSubClassShouldNotHaveObjectIdentity();
            //---------------Test Result -----------------------
            Assert.IsNotNull(rule);
            Assert.AreEqual("DMSingleTableInheritanceSubClassShouldNotHaveObjectIdentity", rule.Name);
            Assert.AreEqual(ErrorLevel.Error, rule.ErrorLevel);
        }

        [Test]
        public void Test_IsValid_WhenSubClassHasPrimaryKey_ShouldFail()
        {
            //---------------Set up test pack-------------------
            DMClass subClass;
            var inheritanceRelationship = GetSubClassWithSuperClassRelationship(out subClass);

            var rule = new DMSingleTableInheritanceSubClassShouldNotHaveObjectIdentity();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(subClass.ObjectIdentity,
                             "The PrimaryKey/ObjectIdentity should not be null for the sub class");
            Assert.AreEqual(ORMapping.SingleTableInheritance, inheritanceRelationship.InheritanceType);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(inheritanceRelationship);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
        }

        [Test]
        public void Test_IsValid_WhenNoSubClassDefined_ShouldPass()
        {
            //---------------Set up test pack------------------
            var inheritanceRelationship = new DMInheritanceRelationship();
            var rule = new DMSingleTableInheritanceSubClassShouldNotHaveObjectIdentity();
            //---------------Assert Precondition----------------
            Assert.IsNull(inheritanceRelationship.SubClass);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(inheritanceRelationship);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid, "Should be valid");
        }
        [Test]
        public void Test_IsValid_WhenInheritanceRelNull_ShouldPass()
        {
            //---------------Set up test pack------------------
            DMInheritanceRelationship inheritanceRelationship = null;
            var rule = new DMSingleTableInheritanceSubClassShouldNotHaveObjectIdentity();
            //---------------Assert Precondition----------------
            Assert.IsNull(inheritanceRelationship);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(inheritanceRelationship);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid, "Should be valid");
        }
        [Test]
        public void Test_IsValid_WhenBONotInheritanceRel_ShouldPass()
        {
            //---------------Set up test pack------------------
            DMClass bo = new DMClass();
            var rule = new DMSingleTableInheritanceSubClassShouldNotHaveObjectIdentity();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(bo);
            Assert.IsNotInstanceOf<DMInheritanceRelationship>(bo);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(bo);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid, "Should be valid");
        }

        [Test]
        public void Test_IsValid_WhenSubClassDoesNotHavePrimaryKey_ShouldPass()
        {
            //---------------Set up test pack-------------------
            var subClass = new DMClass();
            var inheritanceRelationship = new DMInheritanceRelationship {SubClass = subClass};
            var rule = new DMSingleTableInheritanceSubClassShouldNotHaveObjectIdentity();
            //---------------Assert Precondition----------------
            Assert.IsNull(subClass.ObjectIdentity,
                             "The PrimaryKey/ObjectIdentity should be null for the sub class");
            Assert.AreSame(subClass, inheritanceRelationship.SubClass);

            Assert.AreEqual(ORMapping.SingleTableInheritance, inheritanceRelationship.InheritanceType);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(inheritanceRelationship);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid, "Should be valid");
        }
        [Test]
        public void Test_IsValid_WhenNotSingleTableInheritance_AndSubClassHasPrimaryKey_ShouldPass()
        {
            //---------------Set up test pack-------------------
            var subClass = new DMClass();
            subClass.CreateObjectIdentity();
            var inheritanceRelationship = new DMInheritanceRelationship {SubClass = subClass};
            inheritanceRelationship.InheritanceType = ORMapping.ConcreteTableInheritance; ;
            var rule = new DMSingleTableInheritanceSubClassShouldNotHaveObjectIdentity();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(subClass.ObjectIdentity,
                             "The PrimaryKey/ObjectIdentity should be null for the sub class");
            Assert.AreSame(subClass, inheritanceRelationship.SubClass);
            Assert.AreNotEqual(ORMapping.SingleTableInheritance, inheritanceRelationship.InheritanceType);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(inheritanceRelationship);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid, "Should be valid");
        }

        private DMInheritanceRelationship GetSubClassWithSuperClassRelationship(out DMClass childClass)
        {
            var parentDiscriminatorProp = TestUtilsShared.CreateSavedDMProperty();
            TestUtilsDMProperty.SetDMPropIntType(parentDiscriminatorProp);
            parentDiscriminatorProp.Save();

            var subClassWithInheritanceRelationship = new DMInheritanceRelationship();
            var superClass = parentDiscriminatorProp.Class;
            childClass = TestUtilsShared.CreateSavedDMClass(superClass.Assembly);
            subClassWithInheritanceRelationship.SubClass = childClass;
            return subClassWithInheritanceRelationship;
        }

        [Test]
        public void Test_Message_WhenIsValidWasCalled_ShouldReturnCorrectMessage()
        {
            //---------------Set up test pack-------------------
            DMClass subClass;
            var inheritanceRelationship = GetSubClassWithSuperClassRelationship(out subClass);
            var rule = new DMSingleTableInheritanceSubClassShouldNotHaveObjectIdentity();
            rule.IsValid(inheritanceRelationship);
            var expectedMessageStart 
                    = string.Format("The Single Table Inheritance relationship is invalid. The SubClass '{0}' should not have a PrimaryKeyDefined/ObjectIdentifier.", subClass.ClassNameBO);
            const string expectedMessageEnd 
                    = "(With Single Table Inheritance the SubClasses are stored in the same table as the SuperClass and therefore should not have their own PrimaryKey)";
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            var actualMessage = rule.Message;
            //---------------Test Result -----------------------
            StringAssert.Contains(expectedMessageStart, actualMessage);
            StringAssert.Contains(expectedMessageEnd, actualMessage);
        }
        [Test]
        public void Test_Message_WhenIsValidWasNotCalled_ShouldReturnValidMessage()
        {
            //---------------Set up test pack-------------------
            var rule = new DMSingleTableInheritanceSubClassShouldNotHaveObjectIdentity();
            var expectedMessageStart 
                    = string.Format("The Single Table Inheritance relationship is invalid. The SubClass '{0}' should not have a PrimaryKeyDefined/ObjectIdentifier.", "");
            const string expectedMessageEnd 
                    = "(With Single Table Inheritance the SubClasses are stored in the same table as the SuperClass and therefore should not have their own PrimaryKey)";
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            var actualMessage = rule.Message;
            //---------------Test Result -----------------------
            StringAssert.Contains(expectedMessageStart, actualMessage);
            StringAssert.Contains(expectedMessageEnd, actualMessage);
        }
    }
}